package com.strongbj.iot.devices.dam.sub.dacai.request.handle;

import java.io.UnsupportedEncodingException;
import java.net.InetSocketAddress;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;

import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;

import com.strongbj.core.device.Device;
import com.strongbj.core.device.DeviceManager;
import com.strongbj.core.device.IDevice;
import com.strongbj.core.util.ByteUtil;
import com.strongbj.iot.devices.dam.common.AbstractTaskDelayedRunnable;
import com.strongbj.iot.devices.dam.common.DAMManager;
import com.strongbj.iot.devices.dam.common.ITaskManager;
import com.strongbj.iot.devices.dam.message.DAMMessage;
import com.strongbj.iot.devices.dam.message.DAMMessageFactory;
import com.strongbj.iot.devices.dam.response.entity.ISensorFactory;
import com.strongbj.iot.devices.dam.response.entity.SensorEntity;
import com.strongbj.iot.devices.dam.response.entity.SensorFactoryContext;
import com.strongbj.iot.devices.dam.response.entity.TemperatureAndHumiditySensorEntity;
import com.strongbj.iot.devices.dam.response.entity.TemperatureSensorEntity;
import com.strongbj.iot.devices.dam.response.handle.v1.DAMV1Handle;

import io.netty.buffer.Unpooled;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelFutureListener;
import io.netty.channel.ChannelHandlerContext;

/**
 * 更新传感器实时信息
 * 
 * @author yuzhantao
 *
 */
public class UpdateRealtimeSensorDatasHandle extends DAMV1Handle {
	private static Logger logger = LogManager.getLogger(ShowSensorParamsReturnHandle.class.getName());
	private static final DAMMessageFactory damMessageFactory = new DAMMessageFactory(); // DAM消息工厂
	private static final String EMPTY_TEMPERATURE_AND_HUMIDITY_DATAS = "0℃/0RH"; // 空温湿度数据
	private static final String EMPTY_TEMPERATURE_DATAS = "0℃"; // 空温度数据
	private static final int SENSOR_DATA_SIZE = 5; // 一个传感器在协议里的字节长度
	private static final SimpleDateFormat sDateFormat = new SimpleDateFormat("yyyy年MM月dd日hh时mm分ss秒");
	private ISensorFactory sensorFactoryContext = new SensorFactoryContext(); // 传感器工厂类

	// TODO 硬件BUG，实时信息里的传感器类型错误
//	private ISensorFactory sensorFactoryContext = new BugV1SensorFactoryContext(); // 传感器工厂类
	/**
	 * 帧头
	 */
	protected final static String COMMAND_HEADER = "EE";
	/**
	 * 帧尾
	 */
	protected final static String COMMAND_FOOTER = "FFFCFFFF";
	protected final static String COMMAND_CODE = "B112";

	@Override
	protected boolean isHandleDAMMessage(DAMMessage t) {
		if (t.getCommand() == 0x32) {
			return true;
		} else {
			return false;
		}
	}

	@Override
	public Object handle(ChannelHandlerContext ctx, DAMMessage t) {
		// 注册设备信息
		String ip = ((InetSocketAddress) ctx.channel().remoteAddress()).getAddress().getHostAddress();
		IDevice dev = DeviceManager.getInstance().findDevice(ip);
		String deviceCode = ByteUtil.byteArrToHexString(t.getAddressCode());
		if (dev != null) {
			dev.setDeviceCode(deviceCode);
		} else {
			dev = new Device(deviceCode, ip);
			DeviceManager.getInstance().registerDevice(dev);
		}
		
		// 处理温度信息
		int dataLen = t.getDatas().length;
		Map<Short, String> sensorMap = new HashMap<>();
		for (int i = 0; i <= dataLen - SENSOR_DATA_SIZE; i += SENSOR_DATA_SIZE) {
			SensorEntity sensor = sensorFactoryContext.createSensor(t.getDatas(), i);
			short sensorPosition = (short) (i / SENSOR_DATA_SIZE + 1); // 计算传感器位置
			StringBuffer sb = new StringBuffer();
			if (sensor instanceof TemperatureSensorEntity) { // 如果是温度传感器
				int value = ((TemperatureSensorEntity) sensor).getTemperature();
				// TODO 由于温度传感器有时会出现正负1000的现象，故从软件判断如果超过正负100，就不上报
				if (Math.abs(value) >= 100) {
					logger.debug("温度传感器出现错误跳动数据，不予处理，数据值:{}", value);
					continue;
				}

				sb.append(value);
				sb.append("℃");
			} else if (sensor instanceof TemperatureAndHumiditySensorEntity) { // 如果是温湿度传感器
				sb.append(((TemperatureAndHumiditySensorEntity) sensor).getTemperature());
				sb.append("℃");
				sb.append("/");
				sb.append(((TemperatureAndHumiditySensorEntity) sensor).getHumidity());
				sb.append("RH");
			}
			if (sb.toString().equals(EMPTY_TEMPERATURE_AND_HUMIDITY_DATAS)
					|| sb.toString().equals(EMPTY_TEMPERATURE_DATAS)) {
				continue;
			}
			sensorMap.put(sensorPosition, sb.toString());

			sensor = null;
			sb.setLength(0);
		}
		// 更新时间
		String date = sDateFormat.format(new Date());
		sensorMap.put((short) 8, date);

		ITaskManager taskManager = DAMManager.getTaskManager(ByteUtil.byteArrToHexString(t.getAddressCode()));
		taskManager.addSendTask(new AbstractTaskDelayedRunnable() {
			@Override
			protected void taskRun() {
				try {
					sendMessage(ctx, t.getAddressCode(), sensorMap);
				} catch (UnsupportedEncodingException e) {
					e.printStackTrace();
				} finally {
					sensorMap.clear();
				}
			}
		});

		return null;
	}

	private void sendMessage(ChannelHandlerContext ctx, byte[] devAddress, Map<Short, String> sensorMap)
			throws UnsupportedEncodingException {
		if(ctx.channel().isActive()==false) {
			logger.info("", "网络未激活，无法向屏幕下发温度显示命令");
			return;
		}
		byte[] datas = createSensorMessage(devAddress, sensorMap);
		ChannelFuture cf = ctx.channel().writeAndFlush(Unpooled.copiedBuffer(datas));
		cf.addListener(new ChannelFutureListener() {
			@Override
			public void operationComplete(ChannelFuture future) throws Exception {
				if (future.isSuccess()) {
					logger.debug("向屏幕下发温湿度显示命令成功 下发命令={}  ", ByteUtil.byteArrToHexString(datas, true));
				} else {
					logger.error("向屏幕下发温湿度显示命令失败 下发命令={}  ", ByteUtil.byteArrToHexString(datas, true));
				}
			}
		});
	}

	private byte[] createSensorMessage(byte[] devAddress, Map<Short, String> sensorMap)
			throws UnsupportedEncodingException {
		StringBuffer sb = new StringBuffer(COMMAND_HEADER);
		sb.append(COMMAND_CODE);
		sb.append("0001"); // 界面id
		for (Entry<Short, String> item : sensorMap.entrySet()) {
			sb.append(ByteUtil.byteArrToHexString(ByteUtil.shortToByteArr(item.getKey()))); // 控件id
			byte[] datas = item.getValue().getBytes("GBK");
			short dataLen = (short) datas.length;
			sb.append(ByteUtil.byteArrToHexString(ByteUtil.shortToByteArr(dataLen))); // 控件内容长度
			sb.append(ByteUtil.byteArrToHexString(datas)); // 控件内容
		}
		sb.append(COMMAND_FOOTER);

		byte[] retDatas = damMessageFactory.createDAMMessage(ByteUtil.longToBytes(System.currentTimeMillis()),
				devAddress, // 设备编号
				(byte) 0, // 设备类型，默认填0
				(byte) 0, // 版本号，默认填0
				(byte) 0xFF, // 设置设备编号命令
				ByteUtil.hexStringToBytes(sb.toString()) // 设置设备编号
		);

		sb.setLength(0);
		sb = null;

		return retDatas;

	}
}